#include <GL/glew.h>
#include <GL/glut.h>
#include <vector>
#include "mesh.h"
#include "loadModel.h"
#include "vec3.h"
#include <stdio.h>

bool Mesh::load(const char *path, char mirror)
{
	return loadPLY(path, v, c, &bound, mirror);
}

void Mesh::draw()
{
	//Local matrix
	glPushMatrix();

	//Local transform
	glTranslatef(loc.x, loc.y, loc.z);

	//Start drawinig
	glBegin(GL_TRIANGLES);

	//For each vertex
	unsigned int i;
	for (i = 0; i < v.size(); i++)
	{
		//Vertex data
		glColor3f (c[i].x, c[i].y, c[i].z);
		glVertex3f(v[i].x, v[i].y, v[i].z);
	}

	//Stop drawing
	glEnd();

	//Cancel matrix
	glPopMatrix();
}

void Mesh::add(Mesh m)
{
	for (unsigned int i = 0; i < m.v.size(); i++)
	{
		m.v[i].x += m.loc.x;
		m.v[i].y += m.loc.y;
		m.v[i].z += m.loc.z;
		v.push_back(m.v[i]);
		c.push_back(m.c[i]);
	}
}

/* Experiments */

//Constructor
Mesh2::Mesh2()
{
	//Init everything
	vbo = 0;
	vertices = 0;
	colors = 0;
	vcount = 0;
}

//Destructor
Mesh2::~Mesh2()
{
	//Comment out for now, as they are deleted on loading
	//delete [] vertices;
	//delete [] colors;
}

//Set vertices number
void Mesh2::set_vertex_count(int gvcount)
{
	//Delete previous vertices (if exist)
	delete [] vertices;
	delete [] colors;

	//Set new count
	vcount = gvcount;

	//Not zero
	if (vcount)
	{
		//Alocate space for position and colors
		vertices = new float[vcount*3];
		colors   = new float[vcount*3];
	}
	//Zero vertices
	else
	{
		//Nullify
		vertices = 0;
		colors = 0;
	}
}

//Load mesh from file (STILL EXPERIMENTING)
bool Mesh2::load(const char *path, char mirror)
{
	/*std::vector<vec3> vvertices, vcolors;

	loadPLY(path, vvertices, vcolors, 0, mirror);

	set_vertex_count(vvertices.size());

	for (int i = 0; i < vcount; i++)
	{
		vertices[i] = vvertices[i];
		colors[i] = vcolors[i];
	}*/

//	if (loadPly(path, 0) == 0)
//		printf( "error loading file!\n" );
	std::vector<vec3> vert, col;

	loadPLY(path, vert, col, NULL, mirror);
	//loadPly(path, 0);


	//This is the old way to "convert" old PLY parser to mesh (I plan to change it)
	set_vertex_count(vert.size());

	//Move all data to pointers
	int i;
	for (i = 0; i < vcount; i++)
	{
		vertices[i*3  ] = vert[i].x;
		vertices[i*3+1] = vert[i].y;
		vertices[i*3+2] = vert[i].z;

		colors[i*3  ] = col[i].r;
		colors[i*3+1] = col[i].g;
		colors[i*3+2] = col[i].b;

		//Calculate positive and negative bounds
		if (vert[i].x > pbound.x) pbound.x = vert[i].x; else
		if (vert[i].x < nbound.x) nbound.x = vert[i].x;

		if (vert[i].y > pbound.y) pbound.y = vert[i].y; else
		if (vert[i].y < nbound.y) nbound.y = vert[i].y;

		if (vert[i].z > pbound.z) pbound.z = vert[i].z; else
		if (vert[i].z < nbound.z) nbound.z = vert[i].z;
	}

	//Create new VBO
	glGenBuffers(1, &vbo);
	glBindBuffer(GL_ARRAY_BUFFER, vbo);

	//Create buffer data
	glBufferData(GL_ARRAY_BUFFER, sizeof(float) *vcount *3 *2, 
		NULL, GL_STATIC_DRAW);

	//Add vertex positions
	glBufferSubData(GL_ARRAY_BUFFER, 
		0,
		sizeof(float) *vcount *3, 
		vertices);

	//Add vertex colors
	glBufferSubData(GL_ARRAY_BUFFER,
		sizeof(float) *vcount *3,
		sizeof(float) *vcount *3,
		colors);

	//Free pointers (ideally the ply parser could save data to a buffer)
	delete [] vertices;
	delete [] colors;

	//Load complete
	return true;
}

void Mesh2::draw() const
{
	/* Draw mesh using arrays (I might re-use this later) */

	//Enable arrays
	/*glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_COLOR_ARRAY);

	//Pass data to arrays
	glVertexPointer(3, GL_FLOAT, 0, vertices);
	glColorPointer (3, GL_FLOAT, 0, colors  );

	//Draw arrays
	glDrawArrays(GL_TRIANGLES, 0, vcount);

	//Disable arrays
	glDisableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_COLOR_ARRAY);*/

	/* Draw mesh using buffer objects */

	//Make new VBO active. 
	glBindBuffer(GL_ARRAY_BUFFER, vbo);

	//Activate vertex positions and colors
	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_COLOR_ARRAY);

	//How to draw them
	glVertexPointer(3, GL_FLOAT, 0, NULL);
	glColorPointer (3, GL_FLOAT, 0, (void*) (sizeof(float) *vcount *3));

	//Actual draw
	glDrawArrays(GL_TRIANGLES, 0, vcount);

	//Disable
	glDisableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_COLOR_ARRAY);
}
